package cn.minimelon.solon.service.cert.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.minimelon.solon.constants.YesEnum;
import cn.minimelon.solon.domain.cert.*;
import cn.minimelon.solon.mapper.cert.HosAttachMapper;
import cn.minimelon.solon.mapper.cert.HosRegInfoMapper;
import cn.minimelon.solon.mapper.cert.QcPushAuditMapper;
import cn.minimelon.solon.service.cert.FirstPushService;
import cn.minimelon.solon.service.cert.QcHosRegInfoService;
import lombok.extern.slf4j.Slf4j;
import org.beetl.sql.solon.annotation.Db;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Transaction;
import org.noear.solon.data.tran.TranPolicy;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class FirstPushServiceImpl implements FirstPushService {
    @Db("writer")
    private QcPushAuditMapper pushAuditMapper;

    @Db("writer")
    private HosRegInfoMapper hosRegInfoMapper;

    @Db("writer")
    private HosAttachMapper hosAttachMapper;

    @Inject
    private QcHosRegInfoService regInfoService;

    @Override
    public void startFixedRegInfo() {
        List<QcPushInfo> list = pushAuditMapper.selectFixedPushInfo();
        for (QcPushInfo push : list) {
            PushDetailVO regPD = pushAuditMapper.selectPushRegDetail(push);
            List<QcPushAttach> attList = pushAuditMapper.selectPushRegAttach(push);
            this.executePush(push, attList, regPD);
        }
    }

    @Transaction(policy = TranPolicy.required)
    public void executePush(QcPushInfo push, List<QcPushAttach> al, PushDetailVO dl) {
        HosRegInfoVO cert = JSONUtil.toBean(dl.getCertInfo(), HosRegInfoVO.class, true);
        String mfrsId = pushAuditMapper.selectMfrsBySupId(cert.getMfrsId(), push.getHosId(), push.getProvId());
        if (StrUtil.isEmpty(mfrsId)) {
            throw new RuntimeException(StrUtil.format("请供应商【{}】先推送注册人({})", push.getProvName(), cert.getMfrsName()));
        }
        cert.setMasterId(mfrsId);
        List<QcHosAttach> attachList = al.stream()
                .filter(it -> StrUtil.equals(cert.getId(), it.getCertId()))
                .map(it -> copyToHosAttach(it, push.getHosId()))
                .collect(Collectors.toList());
        cert.setAttachList(attachList);
        HosRegInfoVO query = new HosRegInfoVO();
        query.setSupRegId(cert.getId());
        query.setHosId(push.getHosId());
        query.setProvId(push.getProvId());
        HosRegInfoVO old = pushAuditMapper.selectRegListBySupRegId(query);
        if (old == null) {
            log.info("HosRegInfoVO add >>>> {} hosId:{}", cert.getId(), push.getHosId());
            // 不存在则新增医院端注册证
            cert.setOldId(null);
            buildHosRegInfo(cert, push);
            regInfoService.saveOne(cert);
            // 复制产品
            copyRegDetail(cert);
        } else if (StrUtil.equals(cert.getId(), old.getSupRegId())) {
            log.info("HosRegInfoVO update >>>> n:{} o:{}, hosId:{}", cert.getId(), old.getId(), push.getHosId());
            RegDetailVO query2 = new RegDetailVO();
            query2.setPid(cert.getSupRegId());
            List<HosRegDetailVO> list2 = hosRegInfoMapper.selectDetailListByCond(query2);

            RegDetailVO query3 = new RegDetailVO();
            query3.setPid(cert.getSupRegId());
            List<HosRegDetailVO> list3 = hosRegInfoMapper.selectHosDetailListByCond(query3);

            compareDetail(old, list2, list3);

            List<QcHosAttach> attList3 = pushAuditMapper.selectHosRegAttachList(old);
            compareAttach(old, cert.getAttachList(), attList3);
        }
    }

    private void updateHosRegInfo(HosRegInfoVO cert, HosRegInfoVO old, QcPushInfo push) {
        // 已经推送过来更新状态
        HosRegInfoVO update = new HosRegInfoVO();
        update.setId(old.getId());
        update.setActiveFlag(cert.getActiveFlag());
        update.setLastModified(new Date());
        update.setLastModifiedUser(push.getPushUser());
        update.setRegKind(cert.getRegKind());
        update.setCertCode(cert.getCertCode());
        update.setProductName(cert.getProductName());
        update.setBeginDate(cert.getBeginDate());
        update.setEndDate(cert.getEndDate());
        update.setLongTerm(cert.getLongTerm());
        update.setApplyScope(cert.getApplyScope());
        update.setStructure(cert.getStructure());
        update.setHosId(push.getHosId());
        update.setSupRegId(old.getSupRegId());
        regInfoService.update(update);
        // 更新明细
        copyRegDetailChange(update);
        if (!cert.getActiveFlag().equals(old.getActiveFlag())) {
            log.info("update status : {}", old.getId());
        }
        compareAndUpdateAttach(update, cert.getAttachList(), old.getAttachList());
    }

    private void buildHosRegInfo(HosRegInfoVO cert, QcPushInfo push) {
        cert.setSupRegId(cert.getId());
        cert.setPushId(push.getId());
        cert.setHosId(push.getHosId());
        cert.setId(null);
        cert.setCreateUser(push.getPushUser());
        cert.setCreateTime(new Date());
        cert.setLastModifiedUser(push.getPushUser());
        cert.setLastModified(new Date());
    }

    /**
     * 插入产品明细
     */
    private void copyRegDetail(HosRegInfoVO curr) {
        RegDetailVO query = new RegDetailVO();
        query.setPid(curr.getSupRegId()); // 供应商注册证ID
        query.setSpd2DbName("spd");
        List<HosRegDetailVO> details = hosRegInfoMapper.selectDetailListByCond(query);
        if (CollUtil.isNotEmpty(details)) {
            List<HosRegDetailVO> hosDetails = BeanUtil.copyToList(details, HosRegDetailVO.class);
            curr.setDetailList(hosDetails);
            regInfoService.saveDetail(curr);
        }
    }

    private void copyRegDetailChange(HosRegInfoVO curr) {
        RegDetailVO query = new RegDetailVO();
        query.setPid(curr.getSupRegId()); // 供应商注册证ID
        query.setSpd2DbName("spd");
        query.setChange("change");
        List<HosRegDetailVO> details = hosRegInfoMapper.selectDetailListByCond(query);
        if (CollUtil.isNotEmpty(details)) {
            List<HosRegDetailVO> hosDetails = BeanUtil.copyToList(details, HosRegDetailVO.class);
            curr.setDetailList(hosDetails);
            regInfoService.saveDetail(curr);
        }
        // 在把不在 里面的删除
        regInfoService.deleteHosRegDetailByPid(curr);
    }

    protected QcHosAttach copyToHosAttach(QcPushAttach it, String hosId) {
        QcHosAttach att = new QcHosAttach();
        BeanUtil.copyProperties(it, att);
        att.setPushId(it.getPid());
        att.setHosId(hosId);
        return att;
    }

    protected void compareAndUpdateAttach(ICertInfo old, List<? extends QcHosAttach> pushList, List<? extends QcHosAttach> oldList) {
        Map<String, QcHosAttach> updateMap = new HashMap<>();
        for (QcHosAttach att : pushList) {
            att.setId(IdUtil.fastUUID());
            att.setCertId(old.getId());
            att.setHosId(old.getHosId());
            att.setActiveFlag(old.getActiveFlag());
            att.setDelFlag(YesEnum.NO.code());
            updateMap.put(att.getFileId(), att);
        }
        for (QcHosAttach att : oldList) {
            if (updateMap.containsKey(att.getFileId())) {
                updateMap.remove(att.getFileId()); // 文件无需更新
            } else {
                att.setHosId(old.getHosId());
                att.setActiveFlag(old.getActiveFlag());
                att.setDelFlag(YesEnum.YES.code());
                updateMap.put(att.getFileId(), att);
            }
        }
        log.info("compareAndUpdateAttach: {}", old.getId());
    }

    private void compareAttach(ICertInfo old, List<QcHosAttach> list2, List<QcHosAttach> list3) {
        Map<String, QcHosAttach> updateMap = new HashMap<>();
        for (QcHosAttach dd : list2) {
            dd.setId(IdUtil.fastUUID());
            dd.setCertId(old.getId());
            dd.setHosId(old.getHosId());
            dd.setActiveFlag(old.getActiveFlag());
            dd.setDelFlag(YesEnum.NO.code());
            dd.setCreateTime(new Date());
            dd.setLastModified(new Date());
            updateMap.put(dd.getFileId(), dd);
        }
        List<QcHosAttach> updateList = new ArrayList<>();
        for (QcHosAttach dd : list3) {
            if (updateMap.containsKey(dd.getFileId())) {
                updateMap.remove(dd.getFileId()); // 文件无需更新
            } else {
                QcHosAttach up = new QcHosAttach();
                up.setId(dd.getId());
                up.setDelFlag(YesEnum.YES.code());
                up.setActiveFlag(YesEnum.NO.code());
                up.setVersion(dd.getVersion() + 1);
                updateList.add(up);
            }
        }
        if (CollUtil.isNotEmpty(updateMap.keySet())) {
            log.info("compareAttach id:{} goodsIds: {}", old.getId(), updateMap.keySet());
            hosAttachMapper.insertBatch(ListUtil.toList(updateMap.values()));
        }
        if (CollUtil.isNotEmpty(updateList)) {
            log.info("removeAttach id:{} size: {}", old.getId(), updateList.size());
            hosAttachMapper.updateByIdBatch(updateList);
        }
    }

    private void compareDetail(ICertInfo old, List<HosRegDetailVO> list2, List<HosRegDetailVO> list3) {
        Map<String, HosRegDetailVO> updateMap = new HashMap<>();
        for (HosRegDetailVO dd : list2) {
            dd.setId(IdUtil.fastUUID());
            dd.setPid(old.getId());
            dd.setHosId(old.getHosId());
            dd.setActiveFlag(old.getActiveFlag());
            updateMap.put(dd.getProvGoodsId(), dd);
        }
        for (HosRegDetailVO dd : list3) {
            updateMap.remove(dd.getProvGoodsId()); // 文件无需更新
        }
        if (CollUtil.isNotEmpty(updateMap.keySet())) {
            log.info("compareDetail id:{} goodsIds: {}", old.getId(), updateMap.keySet());
        }
    }
}
